package com.example.voyager.ioc;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

public class DefaultBeanFactory implements BeanFactory, BeanDefinitionRegistry{

    //存放bd
    private Map<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

    private Map<String,Object> beanMap = new ConcurrentHashMap<>(256);

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception {
        Objects.requireNonNull(beanName,"注册bean需要输入beanName");
        Objects.requireNonNull(beanName,"注册bean需要输入beanDefinition");
        this.beanDefinitionMap.put(beanName,beanDefinition);
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanName) {
        return this.beanDefinitionMap.get(beanName);
    }

    @Override
    public Boolean containsBeanDefinition(String beanName) {
        return this.beanDefinitionMap.containsKey(beanName);
    }

    @Override
    public <T> T getBean(String beanName) throws Exception {
        return this.deGetBean(beanName);
    }

    private <T> T deGetBean(String beanName) throws Exception {
        Objects.requireNonNull(beanName,"beanName不能为空");
        Object instance = beanMap.get(beanName);

        if(instance != null) return (T) instance;

        BeanDefinition beanDefinition = this.getBeanDefinition(beanName);
        Objects.requireNonNull(beanDefinition,"beanDefinition不能为空");
        Class<?> type = beanDefinition.getBeanClass();

        if(type != null){
            instance = this.createInstanceByConstrutor(beanDefinition);
        }

//        this.doInit(beanDefinition,instance);
        if(beanDefinition.isSingleton()) beanMap.put(beanName,instance);

        return (T) instance;

    }

    //构造方法创建对象
    private Object createInstanceByConstrutor(BeanDefinition beanDefinition) throws IllegalAccessException, InstantiationException {
        return beanDefinition.getBeanClass().newInstance();
    }

    //初始化方法
    private void doInit(BeanDefinition beanDefinition, Object instance) throws Exception{
            Method method = instance.getClass().getMethod(beanDefinition.getInitMethodName(),null);
            method.invoke(instance,null);
    }

}
